﻿//Include("Mz");

/**
 * @fileoverview JavaScript framework 中所有类的基类
 *
 * @author meizz
 * @version 20090908
 * @create-date 20050227
 **/


(function(){
    /**
     * 所有类的实例的统一存放地，key为每个实例的guid
     */
    var instances = {};

    /**
     * Mz.JS框架的基类
     * @name Mz.Class
     * @param {String} guid 可以在类的实例化时指定类的guid
     */
    Mz.Class = function(guid){
        instances[(this.guid = (guid || Mz.Class.guid()))] = this;
    };

    /** @ignore */
    var counter = 0;
    Mz.Class.guid = function(){
        return "MZ__" + (counter ++).toString(36);
    };

    /** @ignore
     * 单例模式：创建一个Class的实例
     * @param {Object} json 直接灌注到这个单例里的预定属性/方法
     */
    Mz.Class.create = function(json){
      var c = new Mz.Class();
      delete instances[c.guid];

      for (var key in json) {
          c[key] = json[key];
      }
      return c;
    };

    /**
     * 根据参数(guid)的指定，返回对应的实例对象引用
     * @param {String} guid 需要获取实例的guid
     * @return {Object/Null} 如果存在的话，返回;否则返回Null。
     */
    window.Instance = Mz.instance = Mz.I = function(guid){
        return instances[guid];
    };
     
    /**
     * 释放对象所持有的资源。
     * 主要是自定义事件。
     * 好像没有将_listeners中绑定的事件剔除掉..
     */
    Mz.Class.prototype.dispose = function(){
        if (this.guid){
            delete instances[this.guid];
        }

        for(var property in this){
            if (typeof this[property] != "function"){
                delete this[property];
            }
        }
    };

    /**
     * 从instances数组中将对象的引用删除掉。
     * 删除之后就无法使用Mz.I()函数获取对象了。
     */
    Mz.Class.decontrol = function(instance){
        if (instance && instance.guid) {
            delete instances[instance.guid];
        }
    };

    /**
     * 重载了默认的toString方法，使得返回信息更加准确一些。
     * @return {String} 对象的String表示形式
     */
    Mz.Class.prototype.toString = function(){
        return "[object " + (this._className || "Object" ) + "]";
    };
})();

/**
 * 这个方法是目前这个框架里唯一对系统 Function 对象污染的一个方法
 * 污染系统对象，实属无奈之举，希望大家谅解
 */
Function.prototype.inherits = function(parentClass, className){
    var i, p, op = this.prototype, C = function(){};
    C.prototype = parentClass.prototype;
    /*
     * 这里用一个空的function来传承 parentClass.prototype 的原因：
     * 在 new C() 创建实例的时候会把 C 的构造函数执行一次，是为了
     * 不因构造函数被执行带来负面影响，不过这也带来了另外一个问题
     * 这种继承只继承了 prototype 而父类的构造函数需要单独的继承
     */
    p = this.prototype = new C();

    /*
     * 这个 className 是为这个类加上一个名字，在Class的toString方法里展现
     */
    if (typeof className == "string"){
        p._className = className;
    }

    /*
     * 下面这个 for...in 是不丢失这种继承之前在 prototype 里定义的元素
     */
    for (i in op){
        p[i]=op[i];
    }
    /*
     * 修正这种继承方法带来的 constructor 被篡改的 bug
     */
    this.prototype.constructor = op.constructor;
    /*
     * 可以通过 superClass 来访问父类定义的prototype方法
     */
    this.superClass = parentClass.prototype;
    op = C = null;
    return p;
};

/* 本 Class 调用的示例：

 //Include("Mz.Class");

 function ChildClass(){
   Mz.Class.call(this);

   //this.property="";
 }
 ChildClass.inherits(Mz.Class, "ChildClassName");

 //class method
 ChildClass.prototype.method=function(){};

 */

/* 一个完美的JS脚本继承的实现

  function ParentClass(){
      //建议：类属性最好都在构造函数里声明
      this.name = "ParentClass";
  }
  //建议：类方法应该在prototype对象上扩展
  ParentClass.prototype.show = function(){
      alert(this.name);
  };

  function ChildClass(){
      //继承父类的构造函数
      ParentClass.apply(this, arguments);
  }
  ChildClass.prototype.show = function(){
      ParentClass.prototype.show.call(this);
  };
  //继承父类的prototype
  ChildClass.inherits(ParentClass, "ChildClass");

 */